<!-- @format -->

<template>
  <div ref="mathContainer" class="math-container">
    <slot></slot>
  </div>
</template>

<script lang="ts">
import { defineComponent, onMounted, onUpdated, ref, watch } from 'vue'
// 导入markdown-it库
import MarkdownIt from 'markdown-it'

export default defineComponent({
  name: 'MathJaxRenderer',
  props: {
    content: {
      type: String,
      default: ''
    },
    options: {
      type: Object,
      default: () => ({})
    }
  },
  setup(props) {
    const mathContainer = ref<HTMLElement | null>(null)
    
    // 创建markdown-it实例
    const md = new MarkdownIt({
      html: true,
      breaks: true,
      linkify: true,
      typographer: true
    })
    
    // 添加自定义规则，防止markdown解析器干扰数学公式
    const defaultRender = md.renderer.rules.text || function(tokens, idx, options, env, self) {
      return self.renderToken(tokens, idx, options)
    }
    
    md.renderer.rules.text = function(tokens, idx, options, env, self) {
      // 检查文本是否包含数学公式标记，如果有则不处理
      const text = tokens[idx].content
      if (text.includes('$') || text.includes('\\(') || text.includes('\\)') || text.includes('\\[') || text.includes('\\]')) {
        console.log('保留原始文本:', text)
        return text
      }
      return defaultRender(tokens, idx, options, env, self)
    }
    
    // 禁用markdown-it中可能干扰数学公式的规则
    md.disable(['backticks', 'emphasis'])
    
    // 配置MathJax
    const configureMathJax = () => {
      window.MathJax = {
        tex: {
          inlineMath: [['\\(', '\\)'], ['$', '$']],
          displayMath: [['$$', '$$']],
          packages: ['base', 'ams', 'noerrors', 'noundefined', 'newcommand', 'boldsymbol'],
          processEscapes: true,  // 允许使用\$来表示文本中的$符号
          processEnvironments: true  // 处理LaTeX环境
        },
        options: {
          enableMenu: false,
          ...props.options,
          renderActions: {
            addMenu: [0, '', ''],
            checkLoading: [1000, () => '', '']
          }
        },
        startup: {
          pageReady: () => {
            console.log('MathJax页面准备完成')
            return window.MathJax.startup.defaultPageReady()
          }
        }
      }
    }

    // 渲染MathJax
    const renderMathJax = () => {
      if (window.MathJax && window.MathJax.typesetPromise) {
        window.MathJax.typesetPromise([mathContainer.value])
          .then(() => {
            console.log('MathJax渲染完成')
          })
          .catch((err: any) => {
            console.error('MathJax渲染错误:', err)
          })
      }
    }

    // 加载MathJax
    const loadMathJax = () => {
      if (!window.MathJax) {
        const script = document.createElement('script')
        script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js'
        script.async = true
        document.head.appendChild(script)
        
        script.onload = () => {
          configureMathJax()
          renderMathJax()
        }
      } else {
        configureMathJax()
        renderMathJax()
      }
    }

    onMounted(() => {
      loadMathJax()
    })

    onUpdated(() => {
      renderMathJax()
    })

    // 处理Markdown和MathJax内容
    const processContent = (content: string) => {
      if (!content) return ''
      
      // 保护数学公式，防止被markdown解析
      const mathExpressions: string[] = []
      
      // 替换块级公式 - 支持$$...$$格式
      let protectedContent = content.replace(/\$\$(.*?)\$\$/gs, (match) => {
        console.log('找到块级公式:', match)
        mathExpressions.push(match)
        return `%%MATH_BLOCK_${mathExpressions.length - 1}%%`
      })
      
      // 替换块级公式 - 支持\[...\]格式
      protectedContent = protectedContent.replace(/\\\[(.*?)\\\]/gs, (match) => {
        console.log('找到块级公式\[...\]:', match)
        mathExpressions.push(match)
        return `%%MATH_BLOCK_${mathExpressions.length - 1}%%`
      })
      
      // 替换行内公式 - 支持\(\)格式
      protectedContent = protectedContent.replace(/\\\((.*?)\\\)/g, (match) => {
        mathExpressions.push(match)
        return `%%MATH_INLINE_${mathExpressions.length - 1}%%`
      })
      
      // 替换行内公式 - 支持$...$格式 - 使用简单但有效的正则表达式
      protectedContent = protectedContent.replace(/\$(.*?)\$/g, (match) => {
        // 排除转义的$符号
        if (match.match(/\\\$/)) {
          return match;
        }
        console.log('找到行内公式:', match)
        // 不转换格式，直接保留$...$格式，因为MathJax已配置支持这种格式
        mathExpressions.push(match)
        return `%%MATH_INLINE_${mathExpressions.length - 1}%%`
      })
      
      // 渲染Markdown
      let htmlContent = md.render(protectedContent)
      
      // 恢复数学公式
      mathExpressions.forEach((expr, index) => {
        // 检查是否存在对应的占位符
        const blockPlaceholder = `%%MATH_BLOCK_${index}%%`;
        const inlinePlaceholder = `%%MATH_INLINE_${index}%%`;
        
        if (htmlContent.includes(blockPlaceholder)) {
          console.log('恢复块级公式:', expr);
          htmlContent = htmlContent.replace(blockPlaceholder, expr);
        }
        
        if (htmlContent.includes(inlinePlaceholder)) {
          console.log('恢复行内公式:', expr);
          htmlContent = htmlContent.replace(inlinePlaceholder, expr);
        }
      })
      
      return htmlContent
    }
    
    // 监听内容变化，重新渲染
    watch(() => props.content, () => {
      if (mathContainer.value && props.content) {
        console.log('处理内容:', props.content)
        // 处理Markdown和MathJax内容
        const processed = processContent(props.content)
        console.log('处理后的HTML:', processed)
        mathContainer.value.innerHTML = processed
        renderMathJax()
      }
    })

    return {
      mathContainer
    }
  }
})
</script>

<style scoped>
.math-container {
  font-family: 'Times New Roman', serif;
  line-height: 1.6;
}
</style>